# Copyright 2007 Joseph Lisee
#
# Author: Joseph Lisee
# License: Public Domain

"""
This module contains a custom GCC-XML tool for SCons
"""

import SCons.Builder
import SCons.Tool
import os, popen2

GCCXMLBuilder = SCons.Builder.Builder(action = "$GCCXML $GCCXML_EXTRA_FLAGS $_XML_CPPINCFLAGS $_XML_CPPDEFFLAGS $SOURCE -fxml=$TARGETS",
                              suffix='xml',
                              src_suffic = ['h', 'hpp'],
                              source_scanner = SCons.Tool.CScanner)
def generate(env):
    if 'GCCXML_PATH' in env:
        gccxml_path = env['GCCXML_PATH']
    else:
        gccxml_path = env.WhereIs('gccxml')
    if 'GCCXML_ROOT' in env:
        gccxml_path = env['GCCXML_ROOT']+'/build/bin/gccxml.exe'
    if gccxml_path is None:
        print 'Could not find gccxml, please make sure it is on your PATH'
        env.Exit(1)
    env['GCCXML'] = gccxml_path
    env['GCCXML_EXTRA_FLAGS'] = ''

    # These variables hold the expanded form of the include and defines lists
    env['_XML_CPPINCFLAGS'] = '$( ${_concat(INCPREFIX, XMLCPPPATH, INCSUFFIX, __env__, RDirs)} $)'
    env['_XML_CPPDFFFLAGS'] = '${_defines(CPPDEFPREFIX, XMLCPPDEFINES, CPPDEFSUFFIX, __env__)}'
    # Added the builder to the given environment
    gccoutput = output = popen2.popen4('echo "" | gcc -x c++ -v -E -dM -')[0].read()
    if env['PLATFORM'] == 'win32':
        lines = gccoutput.split('\n')
        defines = []
        includes = []
        flags=[]
        mode = 'defines'
        def path(p):
            return os.path.normpath(p).replace('\\','/')
        for line in lines:
            line = line.replace('\r','')
            if mode == 'defines' and line.startswith('#define'):
                define = line.strip('#define').strip()
                identifier = define.split(' ')[0]
                expression = define[len(identifier):]
                defines.append((identifier, expression))
            if mode == 'includes' and line.startswith(' '):
                includes.append(line.strip().replace('\\','/'))
            if line.startswith('#include <...>'):
                mode = 'includes'
        for define in defines:
            flags.append('-D%s=\'%s\'' % (define[0], define[1]))
        for include in includes:
            flags.append('-I%s' % (path(include)))
        flags.append('-include %s' % (path(env['GCCXML_ROOT']+'/build/GCC_XML/Support/GCC/4.5/gccxml_builtins.h')))
        flags.append('-iwrapper %s' % (path(env['GCCXML_ROOT']+'/build/GCC_XML/Support/GCC/4.5')))
        gccxmlflags =''
        for flag in flags:
            gccxmlflags += flag+' '
        env['ENV']['GCCXML_FLAGS'] = gccxmlflags
    env.Append(BUILDERS = {'XMLHeader' : GCCXMLBuilder })

def exists(env):
    return env.Detect('gccxml')
